package org.jeecg.common.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;

public class ImageUtil {

//    // 指定jpg图片进行编码
//    public static String toBase64(File imageFile) {
//        // 将图片文件转化为字节数组字符串，并对其进行 Base64 编码处理
//        ByteArrayOutputStream outputStream = null;
//        try {
//            BufferedImage bufferedImage = ImageIO.read(imageFile);
//            outputStream = new ByteArrayOutputStream();
//            ImageIO.write(bufferedImage, "jpg", outputStream);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return Base64.encode(outputStream.toByteArray());
//    }

    public static String getImageType(String imagePath){
        return imagePath.substring(imagePath.lastIndexOf(".") + 1);
    }

    public static String getImageType(File file){
        String imagePath = file.getName();
        return imagePath.substring(imagePath.lastIndexOf(".") + 1);
    }

    public static String imgageToBase64(File imageFile , String imageType) {
        if(!imageFile.exists()){
            throw new JeecgBootException("图片不存在");
        }
        ByteArrayOutputStream outputStream = null;
        try {
            BufferedImage bufferedImage = ImageIO.read(imageFile);
            outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, imageType, outputStream);
        } catch (Exception e) {
            throw new JeecgBootException(e.getMessage());
        }
        return Base64.encode(outputStream.toByteArray());
    }

    public static String bytesToBase64(byte[] bytes) {
        return Base64.encode(bytes);
    }

    public static byte[] base64ToBytes(String base64) {
        return Base64.decode(base64);
    }

    public static String imgageToBase64(String imagePath) {
        if(StringUtils.isEmpty(imagePath)){
            throw new JeecgBootException("图片路径不能为空");
        }
        File imageFile = new File(imagePath);
        String imageType = getImageType(imagePath);
        return imgageToBase64(imageFile , imageType);
    }

    public static String imgageToBase64(String imagePath , String imageType) {
        if(StringUtils.isEmpty(imagePath)){
            throw new JeecgBootException("图片路径不能为空");
        }
        File imageFile = new File(imagePath);
        return imgageToBase64(imageFile , imageType);
    }

    public static void thumbnailImg(File src , int destWidth , int destHeight, File dest) throws IOException {
        BufferedImage bufferedImage = ImageIO.read(src);
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        if(width > height) {
            Thumbnails.of(bufferedImage).width(destWidth).outputQuality(0.7).toFile(dest);
        }else {
            Thumbnails.of(bufferedImage).height(destHeight).outputQuality(0.7).toFile(dest);
        }
    }

    public static void thumbnailImg(String src , int destWidth , int destHeight, String dest) throws IOException {
        File srcFile = new File(src);
        File destFile = new File(dest);
        thumbnailImg(srcFile, destWidth, destHeight, destFile);
    }

    public  static byte[] compressImg(File src  , int destWidth , int destHeight,long destSize) throws Exception {
        long length = src.length();
        BufferedImage bufferedImage = ImageIO.read(src);
        if (length < destSize) {
            String imageType = getImageType(src);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, imageType, outputStream);
            return outputStream.toByteArray();
        }
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        if(width < destWidth){
            destWidth = width;
        }
        if(height < destHeight){
            destHeight = height;
        }

        double quality = getAccuracy(length / 1024);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int count = 0;
        do {
            System.out.println("count=" + count);
            Thumbnails.of(src).scale(1f).outputQuality(quality).toOutputStream(outputStream);
//            if (width > height) {
//                Thumbnails.of(src).width(destWidth).outputQuality(quality).toOutputStream(outputStream);
//            } else {
//                Thumbnails.of(src).height(destHeight).outputQuality(quality).toOutputStream(outputStream);
//            }
            int size = outputStream.size();
//            System.out.println("size=" + size / 1024);
            if (size > destSize) {
                if(count > 10){
                    return outputStream.toByteArray();
                }
                outputStream.reset();
                if (quality > 0.4) {
                    quality -= 0.2;
                }
                destWidth = destWidth * 9 / 10;
                destHeight = destHeight * 9 / 10;
                count ++;
            } else {
                return outputStream.toByteArray();
            }
        } while (true);
    }

    /**
     * 自动调节精度
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 1024) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }


    public  static void compressImg(File src  , int destWidth , int destHeight,long destSize , File dest ) throws Exception {
        byte[] bytes = compressImg(src, destWidth, destHeight, destSize);
        FileUtil.writeBytes(bytes, dest);
    }

    public  static void compressImg(String src , int destWidth , int destHeight , long destSize , String dest ) throws Exception {
        compressImg(new File(src), destWidth, destHeight, destSize, new File(dest));
    }

    public  static String compressImgToBase64(File src  , int destWidth , int destHeight,long destSize) throws Exception {
        byte[] bytes = compressImg(src, destWidth, destHeight, destSize);
        return bytesToBase64(bytes);
    }
    public  static String compressImgToBase64(String src  , int destWidth , int destHeight,long destSize) throws Exception {
        return compressImgToBase64(new File(src) , destWidth , destHeight , destSize);
    }

    public static byte[] imageToBytes(File imgFile) {
        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
        BufferedImage bufferedImage = null;
        try {
            String imageType = getImageType(imgFile);
            bufferedImage = ImageIO.read(imgFile);
            ImageIO.write(bufferedImage, imageType, byteOutput);
            return byteOutput.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (byteOutput != null)
                    byteOutput.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    public static byte[] imageToBytes(String imgFile) {
        return imageToBytes(new File(imgFile));
    }

    public static File bytesToImage(byte[] bytes, File imgFile) {
        ByteArrayInputStream byteInput = new ByteArrayInputStream(bytes);
        BufferedImage bufferedImage = null;
        try {
            bufferedImage = ImageIO.read(byteInput);
            String imageType = getImageType(imgFile);
            ImageIO.write(bufferedImage, imageType, imgFile);
            return imgFile;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (byteInput != null)
                    byteInput.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    public static File bytesToImage(byte[] bytes, String imgFile) {
        return bytesToImage(bytes,new File(imgFile));
    }


    public static void main1(String[] args) throws Exception {
        String srcImg = "D:\\2\\lm0.jpg";
//        String destImg = "D:\\2\\lm00.jpg";
//        thumbnailImg(srcImg, 800,600,destImg);
        System.out.println(compressImgToBase64("D:\\2\\j1.jpg", 800, 600, 200 * 1024));
    }

    public static void main(String[] args) throws Exception {
//        System.out.println(compressImgToBase64("D:\\2\\33.png", 800, 600, 200 * 1024));
        byte[] bytes = compressImg(new File("D:\\2\\33.png"), 800, 600, 200 * 1024);
        bytesToImage(bytes,"D:\\2\\333.png");
    }

}
